package com.impl;


import com.dto.JPushMsgDTO;
import com.dto.MsgDetails;
import com.server.IMsgService;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;



/**
 * Created by jeff on 2017/2/16.
 */
@Service
public class MsgImpl implements IMsgService {

    private Logger logger = LoggerFactory.getLogger(MsgImpl.class);


    @Value("${spring.data.mongodb.collection}")
    private  String msgCollection;

    @Value("${spring.data.mongodb.uri}")
    private  String mongodbUri;

    @Autowired
    private  MongoTemplate mongoTemplate;

    @Override
    public List<MsgDetails> findAll(Long userId, Integer channel) {
        try{
            //设置普通文档
            Query query01 = new Query();
            List<Integer> statusList = new ArrayList<>();
            Criteria criteria=Criteria.where("channel").is(channel).and("userId").is(userId);
            query01.addCriteria(criteria);

            List<MsgDetails>  msgList =  mongoTemplate.find(query01 , MsgDetails.class, msgCollection);


            //获取通知类消息
            Query query02 = new Query();
            Criteria criteria02=Criteria.where("channel").is(channel).and("userId").is(Long.valueOf(0));
            query02.addCriteria(criteria02);
            List<MsgDetails>  shareList =  mongoTemplate.find(query02 , MsgDetails.class, msgCollection);

            for(MsgDetails shareMsg:shareList){
                if(inList(shareMsg.getMsgId(), msgList) == false ){
                    ObjectId objectId = new ObjectId();
                    shareMsg.set_id(objectId.toString());
                    msgList.add(shareMsg);
                }
            }

            List<MsgDetails>  returnList = new ArrayList<>();


                    //处理普通消息
            msgList.forEach((msgDetails) -> {
                if(msgDetails.getStatus() != 3) {
                    if (msgDetails.getUserId() == null || msgDetails.getUserId() == 0) {
                        msgDetails.setUserId(userId);
                    }

                    if (msgDetails.getStatus() == null || msgDetails.getStatus() == 0) {
                        msgDetails.setStatus(1);
                    }
                    returnList.add(msgDetails);
                }

            });

            return  returnList;
        } catch (Exception e) {
            e.printStackTrace();
            logger.info(" find all  error e={}", e);
        }

        return  null;

    }

    @Override
    public long countByStatus(Long userId, Integer status, Integer channel) {
        Query query = new Query();
        Criteria criteria = Criteria.where("channel").is(channel).and("userId").is(userId).and("status").is(status);
        query.addCriteria(criteria);

        long result = this.mongoTemplate.count(query, MsgDetails.class, msgCollection);
        logger.info("result: " + result);

        return result;
    }

    @Override
    public List<MsgDetails> findByType(Long userId, String msgType, Integer channel) {
        try{
            //设置普通文档
            Query query01 = new Query();
            List<Integer> statusList = new ArrayList<>();
            Criteria criteria=Criteria.where("channel").is(channel).and("userId").is(userId).and("msgType").is(msgType);
            query01.addCriteria(criteria);

            List<MsgDetails>  msgList =  mongoTemplate.find(query01 , MsgDetails.class, msgCollection);


            //获取通知类消息
            Query query02 = new Query();
            Criteria criteria02=Criteria.where("channel").is(channel).and("msgType").is(msgType).and("userId").is(Long.valueOf(0));
            query02.addCriteria(criteria02);
            List<MsgDetails>  shareList =  mongoTemplate.find(query02 , MsgDetails.class, msgCollection);

            for(MsgDetails shareMsg:shareList){
                if(inList(shareMsg.getMsgId(), msgList) == false ){
                    ObjectId objectId = new ObjectId();
                    shareMsg.set_id(objectId.toString());
                    msgList.add(shareMsg);
                }
            }

            List<MsgDetails>  returnList = new ArrayList<>();

            //处理普通消息
            msgList.forEach((msgDetails) -> {
                if(msgDetails.getStatus() != 3) {
                    if (msgDetails.getUserId() == null || msgDetails.getUserId() == 0) {
                        msgDetails.setUserId(userId);
                    }

                    if (msgDetails.getStatus() == null || msgDetails.getStatus() == 0) {
                        msgDetails.setStatus(1);
                    }
                    returnList.add(msgDetails);
                }
            });

            return  returnList;


        } catch (Exception e) {
            logger.info(" findByType error e={}", e);
        }

        return  null;
    }

    @Override
    public MsgDetails findOne(Long userId, String msgId, Integer channel) {
        try{
            //设置普通文档
            Query query01 = new Query();
            Criteria criteria=Criteria.where("channel").is(channel).and("userId").is(userId).and("msgId").is(msgId);
            query01.addCriteria(criteria);

            MsgDetails msg  =  mongoTemplate.findOne(query01 , MsgDetails.class, msgCollection);

            if(msg != null){

                String msgContent = msg.getMsgContent();
                if(StringUtils.isNotBlank(msgContent)){
                    msg.setMsgContent(msgContent.replaceAll("\\<.*?>",""));
                }

                return msg;
            }

            //获取通知类消息
            Query query02 = new Query();
            Criteria criteria02=Criteria.where("channel").is(channel).and("msgId").is(msgId).and("userId").is(Long.valueOf(0));
            query02.addCriteria(criteria02);
            msg =  mongoTemplate.findOne(query02 , MsgDetails.class, msgCollection);
            ObjectId objectId = new ObjectId();
            msg.set_id(objectId.toString());

            msg.setUserId(userId);
            msg.setStatus(0);

            String msgContent = msg.getMsgContent();
            if(StringUtils.isNotBlank(msgContent)){
                msg.setMsgContent(msgContent.replaceAll("\\<.*?>",""));
            }

            return msg;
        } catch (Exception e) {
            logger.info(" findOne error e={}", e);
        }

        return  null;
    }


    @Override
    public Boolean updateAllToRead(Long userId, Integer channel) {
        try{
            List<MsgDetails>  msgList =  findAll(userId, channel);
            msgList.forEach((document) -> {
                document.status = 2;
                mongoTemplate.save(document);
            });

            return true;
        } catch (Exception e) {
            logger.info(" updateAllToRead error e={}", e);
            return false;
        }

    }

    @Override
    public Boolean updateAllToRead(Long userId, String msgType, Integer channel) {
        try {
            List<MsgDetails>  msgList =  findByType(userId, msgType, channel);
            msgList.forEach((document) -> {
                document.status = 2;
                mongoTemplate.save(document);
            });

            return true;
        } catch (Exception e) {
            logger.info(" updateAllToRead error e={}", e);
            return false;
        }
    }


    @Override
    public Boolean updateToReadById(Long userId, String msgId, Integer channel) {
        try {
            MsgDetails msg = findOne(userId, msgId, channel);

            if (msg != null) {
                msg.setStatus(2);
                mongoTemplate.save(msg);
            }

            return true;
        } catch (Exception e) {
            logger.info(" updateToReadById error e={}", e);
            return false;
        }
    }

    @Override
    public Boolean deleteAll(Long userId, Integer channel) {

        try {

            List<MsgDetails>  msgList =  findAll(userId, channel);
            msgList.forEach((document) -> {
                document.status = 3;
                mongoTemplate.save(document);
            });

            return true;
        } catch (Exception e) {
            logger.info(" deleteAll error e={}", e);
            return false;
        }
    }

    @Override
    public Boolean deleteAll(Long userId, String msgType, Integer channel) {
        try {
            List<MsgDetails>  msgList =  findByType(userId, msgType, channel);
            msgList.forEach((document) -> {
                document.status = 3;
                mongoTemplate.save(document);
            });


            return true;
        } catch (Exception e) {
            logger.info(" delete all by type  error e={}", e);
            return false;
        }
    }


    @Override
    public Boolean deleteById(Long userId, String msgId, Integer channel) {
        try {
            MsgDetails msg = findOne(userId, msgId, channel);
            msg.setStatus(3);
            mongoTemplate.save(msg);

            return true;
        } catch (Exception e) {
            logger.info(" deleteById error e={}", e);
            return false;
        }
    }

    @Override
    public Boolean saveMsg(JPushMsgDTO dto) {
        MsgDetails msg = new MsgDetails();

        msg.setCts(System.currentTimeMillis());
        msg.setMsgId(dto.getUuid());
        if (StringUtils.isNotEmpty(dto.getAliases())) {
            msg.setUserId(Long.valueOf(dto.getAliases()));
        }else {
            msg.setUserId(0L);// for activity / announcement msg type
        }

        msg.setMsgContent(dto.getMsg());
        msg.setStatus(1);
        msg.setMsgTitle(dto.getTitle());
        msg.setMsgType(dto.getMsgTypeConstants());
        msg.setChannel(dto.getChannel());
        msg.setUrl(dto.getUrl());


        if(msg.get_id() == null){
            ObjectId objectId = new ObjectId();
            msg.set_id(objectId.toString());
        }

        logger.info("saveMsg MsgDetails = {}", msg.toString());

        mongoTemplate.save(msg);

        return true;
    }

    private Boolean inList(String msgId, List<MsgDetails> msgList) {
        Boolean result = false;

        for (MsgDetails msg : msgList) {

            //logger.info("msgId01 = {}, 02={}", msgId, msg.getMsgId());

            if (StringUtils.isBlank(msg.getMsgId()) || StringUtils.isBlank(msgId))
                return false;

            if (msg.getMsgId().equals(msgId)) {
                //logger.info("result =true");
                return true;
            }

            //logger.info("result =false");
        }

        return false;

    }
}





